use std::sync::Arc;
use tokio::net::{TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tracing::{info, error, debug, warn};
use anyhow::{Result, Context};
use serde_json::json;

use crate::devices::control::handler::{ControlHandler, DeviceReply};
use crate::devices::protocol::binary;

#[derive(Debug, Clone, Copy)]
pub enum DeviceMsgType {
    Clipboard = 0,
    AckClipboard = 1,
    UhidOutput = 2,
}

impl DeviceMsgType {
    pub fn from_u8(value: u8) -> Option<Self> {
        match value {
            0 => Some(Self::Clipboard),
            1 => Some(Self::AckClipboard),
            2 => Some(Self::UhidOutput),
            _ => None,
        }
    }
}

pub struct ScrcpySocket {
    reader: Option<OwnedReadHalf>,
    control_handler: Arc<ControlHandler>,
}

impl ScrcpySocket {
    pub async fn connect(
        address: String,
        control_handler: Arc<ControlHandler>,
    ) -> Result<Self> {
        info!("Connecting to scrcpy server at {}", address);

        let stream = TcpStream::connect(&address).await
            .context("Failed to connect to scrcpy server")?;

        let (reader, writer) = stream.into_split();

        // Set writer in control handler
        control_handler.set_writer(writer).await;

        let mut socket = Self {
            reader: Some(reader),
            control_handler,
        };

        // Start reading from socket
        socket.start_reading().await?;

        Ok(socket)
    }

    async fn start_reading(&mut self) -> Result<()> {
        if let Some(reader) = self.reader.take() {
            let control_handler = self.control_handler.clone();

            tokio::spawn(async move {
                if let Err(e) = Self::read_loop(reader, control_handler).await {
                    error!("Socket read loop error: {}", e);
                }
            });
        }

        Ok(())
    }

    async fn read_loop(
        mut reader: OwnedReadHalf,
        control_handler: Arc<ControlHandler>,
    ) -> Result<()> {
        // Read dummy byte
        let mut buf = [0u8; 1];
        reader.read_exact(&mut buf).await
            .context("Failed to read dummy byte")?;
        debug!("Read dummy byte: {:02x}", buf[0]);

        // Read device name (metadata)
        let mut metadata_buf = [0u8; 64];
        let n = reader.read(&mut metadata_buf).await
            .context("Failed to read metadata")?;

        if n > 0 {
            let mut end = n;
            while end > 0 && metadata_buf[end - 1] == 0 {
                end -= 1;
            }
            
            if end > 0 {
                let device_name = std::str::from_utf8(&metadata_buf[..end])
                    .context("Invalid device name")?;
                
                info!("Connected to device: {}", device_name);
                
                // Send device metadata reply
                // Note: In the actual implementation, this would be sent through the reply channel
                debug!("Device metadata received: {}", device_name);
            }
        }

        // Main message loop
        loop {
            match reader.read_u8().await {
                Ok(msg_type_byte) => {
                    let msg_type = match DeviceMsgType::from_u8(msg_type_byte) {
                        Some(t) => t,
                        None => {
                            warn!("Unknown message type: {}", msg_type_byte);
                            continue;
                        }
                    };

                    if let Err(e) = Self::handle_device_message(
                        msg_type,
                        &mut reader,
                        &control_handler,
                    ).await {
                        error!("Failed to handle device message: {}", e);
                    }
                }
                Err(e) => {
                    error!("Failed to read message type: {}", e);
                    break;
                }
            }
        }

        info!("Socket read loop ended");
        Ok(())
    }

    async fn handle_device_message(
        msg_type: DeviceMsgType,
        reader: &mut OwnedReadHalf,
        _control_handler: &Arc<ControlHandler>,
    ) -> Result<()> {
        match msg_type {
            DeviceMsgType::Clipboard => {
                let text_length = reader.read_u32().await
                    .context("Failed to read clipboard text length")?;
                
                let mut buf = vec![0u8; text_length as usize];
                reader.read_exact(&mut buf).await
                    .context("Failed to read clipboard text")?;
                
                let text = String::from_utf8(buf)
                    .context("Invalid clipboard text")?;
                
                debug!("Device clipboard changed: {}", text);
                // Send clipboard reply through handler
            }
            DeviceMsgType::AckClipboard => {
                let sequence = reader.read_u64().await
                    .context("Failed to read clipboard ack sequence")?;
                
                debug!("Clipboard set acknowledged: sequence {}", sequence);
                // Send ack reply through handler
            }
            DeviceMsgType::UhidOutput => {
                let id = binary::read_16be(&[
                    reader.read_u8().await?,
                    reader.read_u8().await?,
                ]);
                
                let size = binary::read_16be(&[
                    reader.read_u8().await?,
                    reader.read_u8().await?,
                ]);
                
                let mut data = vec![0u8; size as usize];
                reader.read_exact(&mut data).await
                    .context("Failed to read UHID output data")?;
                
                debug!("UHID output: id={}, size={}", id, size);
                // Send UHID output reply through handler
            }
        }
        
        Ok(())
    }

    pub async fn close(self) {
        info!("Closing scrcpy socket");
        drop(self.reader);
    }
}